第2章 动态分析技术

pizza大佬和阿鹏大佬之前推荐了xdbg,我也觉得xdbg的界面看起来更舒服。但在这一章里面xdbg篇幅很少,主要篇幅为ollydbg和windbg,不过主要的功能应该调试器都有,因此决定照着ollydbg的功能去摸索xdbg对应的功能,windbg较为硬核,待接触到内核部分再去了解。

TraceMe.exe流程分析

进入到子程序后,若想回看刚才单步跟踪的代码,可以按“-”(减号)键;若想让光标回到当前EIP,可以双击EIP寄存器

Ctrl+F9:执行到返回指令处

Alt+F9:执行到用户代码

获取文本框中的字符,通常使用GetDlgItemText或者GetWindowText函数

GetDlgItemText函数执行后,会把取出的文本放到由lpString指定的位置,是第三个参数

TraceMe.exe破解脚本:

#部分输入和常量表进行运算,直接照着校验逻辑写破解脚本即可;后续可把用户名随机生成从而得到序列号集
const = [0x0C, 0x0A, 0x13, 0x09, 0x0C, 0x0B, 0x0A, 0x08]
name = "obliviate"
sum = 0
j = 0
for i in range(3,len(name)):
    sum += ord(name[i]) * const[j]
    j += 1
print(sum)

常用断点

INT3

最常用,把指令机器码改成0xCC;绕过检测可以把断点设在函数内

硬件断点

对着想要断下的地址右键-断点-硬件断点,即可断下,最多可设置4个

原理:和DRx调试寄存器(DR0~DR7)有关

DR0~DR3:调试地址寄存器,保存硬件断点监视的地址

DR4~DR5:保留

DR6:调试寄存器组状态寄存器,用于记录是在哪个硬件断点断下。如果是DR0,那么DR6的第0位(最低位)被置1;如果是DR1,那么DR6的第1位置1,以此类推。

DR7:调试寄存器组控制寄存器

L0和G0(各1位):控制DR0是全局断点还是局部断点,G0=1则为全局,L0=1则为局部,L0/G0~L3/G3同理

LEN0(2位):指定断点下断的长度,00为1字节,01为2字节,11为4字节,LEN1~LEN3同理

R/W0:指定断点触发条件,00为只执行,01为写入数据,10为I/O端口断点,11为读或写数据断点,R/W1~3同理

GD:保护DRx,如果GD位为1,对DRx的任何访问都会触发int 1

内存断点

同上,对着想要断下的地址右键-断点-内存断点,最多可设置1个

原理:对所设的地址赋予不可访问/不可写属性,这样当访问/写入时就会产生异常

硬件访问/写入断点是在触发硬件断点的下一条指令处断下,而内存断点是在触发断点的指令处断下

消息断点

在句柄选项中的窗口列表,根据文本信息(比如一个按钮会有按钮上的字)找到相应的句柄,右击-消息断点,然后选择断在哪种消息。比如要在鼠标左键点击断下,就选择WM_LBUTTONUP

条件断点

对着要断的地址,右键-条件断点,之后设置条件

条件消息断点

在条件断点的基础上,可以选择输出日志,格式参考:http://help.x64dbg.com/en/latest/introduction/Formatting.html

比如输出寄存器eax的值,使用{eax};

输出某个地址的值,使用{mem;size@addr},其中size为字节数,addr为地址,但这个需要注意输出日志似乎是大端序